package com.gemantic.gitlab.util;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gemantic.gitlab.dto.TagDto;

import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * @author xujian
 * @date 2020-10-30 11:31
 **/
@Slf4j
@Component
public class GitLabApiUtils {
    private static String getProjectMembersUrl;
    private static String getGroupMembersUrl;
    private static String getTagsUrl;
    private static String createTagsUrl;
    private static String token;

   private static final String authHeaderName = "PRIVATE-TOKEN";

    @Value("${project.members.api.url}")
    public void setGetProjectMembersUrl(String getProjectMembersUrl) {
        GitLabApiUtils.getProjectMembersUrl = getProjectMembersUrl;
    }

    @Value("${group.members.api.url}")
    public void setGetGroupMembersUrl(String getGroupMembersUrl) {
        GitLabApiUtils.getGroupMembersUrl = getGroupMembersUrl;
    }


    @Value("${project.tags.api.url}")
    public void setTagsUrl(String tagsUrl) {
        GitLabApiUtils.getTagsUrl = tagsUrl;
    }

    @Value("${project.create.tags.api.url}")
    public void setCreateTagsUrl(String createTagsUrl) {
        GitLabApiUtils.createTagsUrl = createTagsUrl;
    }

    @Value("${gitlab.token}")
    public void setToken(String token) {
        GitLabApiUtils.token = token;
    }

    /**
     * 获取所以项目成员
     *
     * @param projectId
     * @return
     */
    public static List<String> getAllProjectMembers(Integer projectId) {
        getProjectMembersUrl = getProjectMembersUrl.replace("$", "" + projectId);
        getGroupMembersUrl = getGroupMembersUrl.replace("$", "" + projectId);
        List<String> projectMasterMembers = getGitLabMasterMembers(getProjectMembersUrl);
        List<String> groupMasterMembers = getGitLabMasterMembers(getGroupMembersUrl);
        return Stream.of(projectMasterMembers, groupMasterMembers).flatMap(Collection::stream).distinct().collect(Collectors.toList());
    }

    public static String getLatestTagName(Integer projectId, String type) {
        getTagsUrl = getTagsUrl.replace("$", "" + projectId);
        String latestTagName = getLatestTagName(getTagsUrl);
        if (latestTagName == null) {
            return null;
        }
        String[] oldTag = latestTagName.split("-");
        String versionNum = oldTag[oldTag.length - 1];
        String[] versionNumArray = versionNum.split("\\.");
        String num = versionNumArray[versionNumArray.length - 1];
        Integer currentNum = Integer.parseInt(num) + 1;
        String newVersion = "";
        for (int i = 0; i < versionNumArray.length - 1; i++) {
            newVersion += versionNumArray[i] + ".";
        }
        newVersion += currentNum;

        return getNewTag(type, newVersion);
    }

    public static String getNewTag(String type, String version) {
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String format = dateFormat.format(new Date());
        return "release" + "-" + type + "-" + format + "-" + version;
    }

    /**
     * 获取master成员
     *
     * @param url
     * @return
     */
    private static List<String> getGitLabMasterMembers(String url) {
        List<String> result = new ArrayList<>();
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(url).header(authHeaderName, token).build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            String body = response.body().string();
            JSONArray jsonArray = JSONArray.parseArray(body);
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                if (jsonObject.getInteger("access_level") == 40) {
                    result.add(jsonObject.getString("name"));
                }
            }
        } catch (IOException e) {
            log.error("调用GitLab API失败！", e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return result;
    }


    protected static String getLatestTagName(String url) {
        OkHttpClient okHttpClient = new OkHttpClient();
        Request request = new Request.Builder().url(url).header(authHeaderName, token).build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            String body = response.body().string();
            List<TagDto> tagDtoList = JSONArray.parseArray(body).toJavaList(TagDto.class);
            tagDtoList.sort(Comparator.comparing(tagItem -> tagItem.getCommit().getCommitted_date()));
            return tagDtoList.get(tagDtoList.size() - 1).getName();
        } catch (IOException e) {
            log.error("调用GitLab API失败！", e);
            return null;
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    public static void createTag(Integer projectId, String tagName, String ref, String message, String releaseDescription) {
        OkHttpClient okHttpClient = new OkHttpClient();
        String url = createTagsUrl.replace("$1", "" + projectId)
                .replace("$2", tagName)
                .replace("$3", ref)
                .replace("$4", message)
                .replace("$5", releaseDescription);

        Request request = new Request.Builder().url(url)
                .post(RequestBody.create("{}", MediaType.parse("application/json; charset=utf-8")))
                .header(authHeaderName, token).build();
        Response response = null;
        try {
            response = okHttpClient.newCall(request).execute();
            String body = response.body().string();
            JSONObject parse = JSONObject.parseObject(body);
            if (tagName.equals(parse.getString("name"))) {
                log.info("创建tag成功！{}", body);
            } else {
                log.error("创建tag失败！{}", body);
            }
        } catch (IOException e) {
            log.error("调用GitLab API失败！", e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }
}
